#include "StdAfx.h"
#include "Organ.h"
#include <cmath>

COrgan::COrgan(void)
{
	m_amp = 1.0;
	m_time = 0;
	m_drawbars.resize(9,0.0);
	m_drawbars[0] = 8.0;

	m_harmonics.resize(9, 0);
	m_harmonics[0] = 1;
	m_harmonics[1] = 2;
	m_harmonics[2] = 3;
	m_harmonics[3] = 4;
	m_harmonics[4] = 6;
	m_harmonics[5] = 8;
	m_harmonics[6] = 10;
	m_harmonics[7] = 12;
	m_harmonics[8] = 16;
	
	m_VibratoFrequency = 0;
	m_VibratoMagnitude = 0;

	m_LeslieAttackTime = 0;
	m_LeslieReleaseTime = 0;
	m_LeslieRadius = 0;
	m_LeslieStartFrequency = 0;
}

COrgan::~COrgan(void)
{
}


void COrgan::Start()
{
    m_phase = 0;
	m_VibratoPhase = 0;
	m_LesliePhase = 0;
}

bool COrgan::Generate()
{
	double sample = 0;
	double LeslieChange,VibratoChange;
	double ATTACK,RELEASE;
	double Simp1,Simp2,Simp3;
	double SimpPhase,SimpPhase2;
    for(int i=0;i<9;i++)
	{
			sample += m_drawbars[i]*sin(m_phase*m_harmonics[i]);
	}
	double VibratoMagnitudeTemp=(m_VibratoMagnitude/100.0)*m_freq;

	LeslieChange = (1 + (cos(m_LesliePhase)/340.29)*(m_LeslieRadius));
	VibratoChange = sin(m_VibratoPhase)*VibratoMagnitudeTemp;

	ATTACK = m_LeslieAttackTime * GetSampleRate();
	RELEASE = m_duration - (m_LeslieReleaseTime * GetSampleRate());

	sample = sample * m_amp;
    m_frame[0] = sample;
	m_frame[1] = sample;

	SimpPhase = ((m_freq+VibratoChange)*LeslieChange);
	SimpPhase = SimpPhase*2*PI*GetSamplePeriod();
	m_phase = m_phase + SimpPhase;

	SimpPhase2 = m_VibratoFrequency;
	SimpPhase2 = SimpPhase2*2*PI*GetSamplePeriod();
	m_VibratoPhase = m_VibratoPhase + SimpPhase2;
	
	if((m_time<ATTACK) && m_LeslieChanged)
	{
		Simp1 = (m_LeslieStartFrequency+((m_LeslieFrequency-m_LeslieStartFrequency)*(m_time/ATTACK)));
		Simp1 = Simp1*2*PI*GetSamplePeriod();
		m_LesliePhase = m_LesliePhase + Simp1;
	}
	else if(m_time>RELEASE)
	{
		Simp2 = (m_LeslieEndFrequency+((m_LeslieFrequency-m_LeslieEndFrequency)*(1-((m_time-RELEASE)/(m_duration-RELEASE)))));
		Simp2 = Simp2*2*PI*GetSamplePeriod();
		m_LesliePhase = m_LesliePhase + Simp2;
		m_LeslieStartFrequency = m_LeslieEndFrequency;
	}
	else
	{
		Simp3 = m_LeslieFrequency;
		Simp3 = Simp3*2*PI*GetSamplePeriod();
		m_LesliePhase = m_LesliePhase + Simp3;
	}
	m_time++;
    return true;
}
